/** @file         led_drv.h
 *  @brief        驱动。
 *  @details      led 驱动程序员。主要是 file_operations
 *  @author       lzm
 *  @date         2021-03-06 10:18:03
 *  @version      v1.0
 *  @copyright    Copyright By lizhuming, All Rights Reserved
 *
 **********************************************************
 *  @LOG 修改日志:
 **********************************************************
*/

/* 系统库 */
#include <linux/init.h>
#include <linux/module.h>
#include <linux/cdev.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
#include <linux/io.h>

/* 私人库 */
#include "led_resource.h"

/* 常量 */
#define LED_DEV_NAME "led" // 设备名称
#define LED_DEV_CNT  (3)       // 设备数量
#define LED_DEV_INODE_NAME "led_dev" // 设备节点名称
#define LED_DEV_CLASS "led_dev_class" // 设备类名称 （*用于设备节点*）


/* led device id. 设备数组下标，也是次设备号。 */
typedef enum
{
    led_dev_id_1_e = 0,
    led_dev_id_2_e,
    led_dev_id_3_e,

    led_dev_cnt_e,
}led_dev_id_e;

/* my led pin register data struct (MMU) */
typedef struct
{
    led_resource_t *resource; // led 资源  

    unsigned int __iomem *va_dr; // 数据寄存器  虚拟地址
	unsigned int __iomem *va_gdir; // 输入输出寄存器  虚拟地址
	unsigned int __iomem *va_iomuxc_mux; // 端口复用寄存器  虚拟地址
	unsigned int __iomem *va_ccm_ccgrx; // 端口时钟寄存器  虚拟地址
	unsigned int __iomem *va_iomux_pad; // 电气属性寄存器  虚拟地址

    unsigned int pin; // 引脚号
    unsigned int clock_offset; // 时钟偏移
}led_pin_t;


/* my led device struct */
typedef void (*led_init_f)(unsigned char);
typedef void (*led_exit_f)(unsigned char);
typedef void (*led_ctrl_f)(unsigned char, unsigned char);
typedef struct
{
    /* 设备 ID 次设备号-1 */
    unsigned char id;
    /* 设备名称 */
    char name[10]; // 限定十个字符

    /* 设备参数 */
    dev_t dev_num; // 设备号
    struct cdev dev; // 内核设备文件 结构体

    /* led 状态 */
    unsigned char status; // 0: 关闭； 1：开

    /* 引脚参数 */
    led_pin_t *pin_data;

    /* 设备函数 */
    led_init_f init; // 初始化函数
    led_exit_f exit; // 出口函数
    led_ctrl_f ctrl; // 控制函数
}led_dev_t;

/* 广播 */

void led_dev_init(void);
int led_dev_open(struct inode *inode, struct file *filp);
int led_dev_release(struct inode *inode, struct file *filp);
ssize_t led_dev_write(struct file *filp, const char __user * buf, size_t count, loff_t *ppos);
ssize_t led_dev_read(struct file *filp, const char __user * buf, size_t count, loff_t *ppos);
void led_chrdev_init(void);
